﻿
using System;
using System.Resources;
using System.Runtime.Serialization;

namespace Integra.PresentacionWindows.Base.Excepcion
{
    /// <summary>
    /// Clase para excepciones de aplicación
    /// </summary>
    [Serializable()]
    public class Excepcion : System.ApplicationException, ISerializable
    {
        private string[] mpstrParams = null;
        private string mstrKeyMensaje;
        private string mstrMensaje = "";
        private string mstrAssemblyResource = "IASoft.IABase.Comun.Excepcion";
        private TipoExcepcion mintTipo = TipoExcepcion.Vacio;
        private TipoPermanenciaExcepcion mintTipoPermanencia = TipoPermanenciaExcepcion.Vacio;

        #region Constructores

        #region Serialización
        /// <summary>
        /// Serializa la excepción
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        public new void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Params", mpstrParams, typeof(string[]));
            info.AddValue("KeyMensaje", mstrKeyMensaje);
            info.AddValue("Mensaje", mstrMensaje);
            info.AddValue("AssemblyResource", mstrAssemblyResource);
            info.AddValue("Tipo", mintTipo, typeof(TipoExcepcion));
            info.AddValue("TipoPermanencia", mintTipoPermanencia, typeof(TipoPermanenciaExcepcion));
        }

        /// <summary>
        /// Desserializa la excepción
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        public Excepcion(SerializationInfo info, StreamingContext context)
        {
            mpstrParams = (string[])info.GetValue("Params", typeof(string[]));
            mstrKeyMensaje = (string)info.GetValue("KeyMensaje", typeof(string));
            mstrMensaje = (string)info.GetValue("Mensaje", typeof(string));
            mstrAssemblyResource = (string)info.GetValue("AssemblyResource", typeof(string));
            mintTipo = (TipoExcepcion)info.GetValue("Tipo", typeof(TipoExcepcion));
            mintTipoPermanencia = (TipoPermanenciaExcepcion)info.GetValue("TipoPermanencia", typeof(TipoPermanenciaExcepcion));
        }
        #endregion

        #region externas
        /// <summary>
        /// Crea una excepción indicando el nombre del fichero de recursos donde se encuentra el key del mensaje
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="AssemblyResource">Nombre del fichero de recursos sin la preposición GIR.Trans.</param>
        /// <param name="Tipo">Tipo de error</param>
        public Excepcion(string KeyMensaje, string AssemblyResource, TipoExcepcion Tipo)
            : base(KeyMensaje)
        {
            mstrKeyMensaje = KeyMensaje;
            mstrAssemblyResource = AssemblyResource;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción indicando el nombre del fichero de recursos donde se encuentra el key del mensaje<BR/>
        /// Recibe parametros para ser cambiados en el mensaje
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="AssemblyResource">Nombre del fichero de recursos sin la preposición GIR.Trans.</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="pValues">Valores de los parametros del mensaje de error</param>
        public Excepcion(string KeyMensaje, string AssemblyResource, TipoExcepcion Tipo, params string[] pValues)
            : base(KeyMensaje)
        {
            mpstrParams = pValues;
            mstrKeyMensaje = KeyMensaje;
            mstrAssemblyResource = AssemblyResource;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción indicando el nombre del fichero de recursos donde se encuentra el key del mensaje<BR/>
        /// Se especifica la excepción origen<BR/>
        /// Recibe parametros para ser cambiados en el mensaje
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="AssemblyResource">Nombre del fichero de recursos sin la preposición GIR.Trans.</param>
        /// <param name="inner">Excepción previa</param>
        public Excepcion(string KeyMensaje, string AssemblyResource, TipoExcepcion Tipo, Exception inner)
            : base(KeyMensaje, inner)
        {
            mstrKeyMensaje = KeyMensaje;
            mstrAssemblyResource = AssemblyResource;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción indicando el nombre del fichero de recursos donde se encuentra el key del mensaje<BR/>
        /// Se especifica la excepción origen
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="AssemblyResource">Nombre del fichero de recursos sin la preposición GIR.Trans.</param>
        /// <param name="inner">Excepción previa</param>
        /// <param name="pValues">Valores de los parametros del mensaje de error</param>
        public Excepcion(string KeyMensaje, string AssemblyResource, TipoExcepcion Tipo, Exception inner, params string[] pValues)
            : base(KeyMensaje, inner)
        {
            mpstrParams = pValues;
            mstrKeyMensaje = KeyMensaje;
            mstrAssemblyResource = AssemblyResource;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción indicando el nombre del fichero de recursos donde se encuentra el key del mensaje<BR/>
        /// La permanencia marca la vida de la excepción.
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="AssemblyResource">Nombre del fichero de recursos sin la preposición GIR.Trans.</param>
        /// <param name="TipoPermanencia">Tipo de permanencia de la excepción</param>
        public Excepcion(string KeyMensaje, string AssemblyResource, TipoExcepcion Tipo, TipoPermanenciaExcepcion TipoPermanencia)
        {
            mstrKeyMensaje = KeyMensaje;
            mstrAssemblyResource = AssemblyResource;
            mintTipo = Tipo;
            mintTipoPermanencia = TipoPermanencia;
        }
        #endregion

        #region Internas
        /// <summary>
        /// Crea una excepción generica, el key del mensaje se buscará en Comun.Base.Excepcion
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        public Excepcion(string KeyMensaje, TipoExcepcion Tipo)
            : base(KeyMensaje)
        {
            mstrKeyMensaje = KeyMensaje;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción generica, el key del mensaje se buscará en IASoft.IABase.Comun.Recursos
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="pValues">Lista de parametros para cambiar en el mensaje</param>
        public Excepcion(string KeyMensaje, TipoExcepcion Tipo, params string[] pValues)
            : base(KeyMensaje)
        {
            mpstrParams = pValues;
            mstrKeyMensaje = KeyMensaje;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción generica, el key del mensaje se buscará en IASoft.IABase.Comun.Recursos<BR/>
        /// Se especifica la excepción origen
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="inner">Excepción origen</param>
        public Excepcion(string KeyMensaje, TipoExcepcion Tipo, Exception inner)
            : base(KeyMensaje, inner)
        {
            mstrKeyMensaje = KeyMensaje;
            mintTipo = Tipo;
        }

        /// <summary>
        /// Crea una excepción generica, el key del mensaje se buscará en DSWeb.Excepcion<BR/>
        /// Se especifica la excepción origen<BR/>
        /// Recibe parametros para ser cambiados en el mensaje
        /// </summary>
        /// <param name="KeyMensaje">Identificador del recurso del mensaje</param>
        /// <param name="Tipo">Tipo de error</param>
        /// <param name="inner">Excepción origen</param>
        /// <param name="pValues">Lista de parametros para cambiar en el mensaje</param>
        public Excepcion(string KeyMensaje, TipoExcepcion Tipo, Exception inner, params string[] pValues)
            : base(KeyMensaje, inner)
        {
            mpstrParams = pValues;
            mstrKeyMensaje = KeyMensaje;
            mintTipo = Tipo;
        }
        #endregion

        #endregion

        /// <summary>
        /// Mensaje de la excepción
        /// </summary>
        public override string Message
        {
            get
            {
                if (mstrMensaje.Length == 0)
                {
                    //TODO: Comentado por que no hay assembly de errores
                    //mstrMensaje = RecursosBase.GetString(mstrAssemblyResource, mstrKeyMensaje);
                    mstrMensaje = "";
                    if (mstrMensaje == null) { mstrMensaje = ""; }
                    else
                    {
                        for (int i = 0; mpstrParams != null && i < mpstrParams.Length; i++)
                        {
                            mstrMensaje = mstrMensaje.Replace("{" + i + "}", mpstrParams[i]);
                        }
                        mpstrParams = null;
                    }
                }
                return mstrMensaje;
            }
        }

        /// <summary>
        /// Mensaje de la excepción previa
        /// </summary>
        public string MensajePrevio
        {
            get
            {
                string strOriginalMensaje = "";
                if (this.InnerException != null)
                {
                    strOriginalMensaje = this.InnerException.Message;
                }
                return strOriginalMensaje;
            }
        }

        /// <summary>
        /// Cadena que muestra la ruta de las excepciones que se han ido produciendo
        /// </summary>
        public string ShortStackTrace
        {
            get
            {
                string strStackTrace = Message;
                Exception e = this.InnerException;

                while (e != null)
                {
                    strStackTrace += '\n';
                    if (e is Excepcion)
                    {
                        strStackTrace += ((Excepcion)e).ShortStackTrace;
                        break;//El proceso lo terminara mi inner
                    }
                    else
                    {
                        strStackTrace += e.Message;
                        e = e.InnerException;
                    }
                }
                return strStackTrace;
            }
        }

        /// <summary>
        /// Tipo de la excepción
        /// </summary>
        public TipoExcepcion Tipo
        {
            get
            {
                return mintTipo;
            }
        }

        /// <summary>
        /// Tipo de permanencia de la excepción
        /// </summary>
        public TipoPermanenciaExcepcion TipoPermanencia
        {
            get
            {
                return mintTipoPermanencia;
            }
        }

        /// <summary>
        /// Identificador del mensaje
        /// </summary>
        public string KeyMensaje
        {
            get
            {
                return mstrKeyMensaje;
            }
        }

        public static Excepcion FromException(Exception ex)
        {
            if (ex is Excepcion)
                return (Excepcion)ex;
            else
                return new Excepcion("ErrorDesconocido", TipoExcepcion.Error, ex);
        }
    }

    /// <summary>
    /// Enumeración que contiene los posibles tipos de excepción.<BR/>
    ///		
    /// Versión: 
    ///		1.00
    /// Autor: 
    ///		Manuel Pereda
    /// </summary>
    [Serializable]
    public enum TipoExcepcion
    {
        /// <summary>
        /// No realiza ninguna acción
        /// </summary>
        Vacio = 0,
        /// <summary>
        /// Muestra un mensaje en pantalla con si/no
        /// </summary>
        Pregunta,
        /// <summary>
        /// Muestra un mensaje en pantalla con un boton salir y un icono de esclamación
        /// </summary>
        Informativo,
        /// <summary>
        /// Muestra un mensaje en pantalla con un boton salir y un icono
        /// <BR/>Se utiliza para los mensajes que no provienen de nuestro programa
        /// </summary>
        Error,
        /// <summary>
        /// Muestra un mensaje en pantalla con un boton salir y un icono
        /// <BR/>Se utiliza para los mensajes que provienen de nuestro programa
        /// </summary>
        ErrorConocido,
        /// <summary>
        /// Muestra un mensaje en pantalla con un boton salir y un icono
        /// <BR/>Se utiliza para los mensajes que provienen de nuestro programa producidor por un error de codificación
        /// </summary>
        ErrorControl
    };

    /// <summary>
    /// Enumeración que contiene los posibles tipos de permanencia de una excepción.<BR/>
    /// </summary>
    [Serializable]
    public enum TipoPermanenciaExcepcion
    {
        /// <summary>
        /// No realiza ninguna acción
        /// </summary>
        Vacio = 0,
        /// <summary>
        /// Mantiene la ausencia durante la vida del formulario activo
        /// </summary>
        FormularioActivo
    };
}
